// pkg/middleware/auth.go
package middleware

import (
	"star-go-app/internal/apps/auth/models"
	"star-go-app/internal/apps/auth/serializers"
	"star-go-app/internal/apps/auth/services"
	"star-go-app/pkg/common/utils/response"
	"star-go-app/pkg/infra/config"
	"star-go-app/pkg/infra/database"
	"strings"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

// AuthMiddleware 认证中间件结构
type AuthMiddleware struct {
	authService services.AuthService
	db          *gorm.DB
}

// NewAuthMiddleware 创建认证中间件实例
func NewAuthMiddleware() *AuthMiddleware {
	return &AuthMiddleware{
		authService: services.NewAuthService(),
		db:          database.GetDB(),
	}
}

// RequireAuth 基础认证中间件 - 要求用户登录且账户正常
func RequireAuth() gin.HandlerFunc {
	middleware := NewAuthMiddleware()
	return middleware.requireAuth()
}

// RequirePermissions 权限认证中间件 - 要求用户拥有指定权限(AND逻辑)
func RequirePermissions(permissions ...string) gin.HandlerFunc {
	middleware := NewAuthMiddleware()
	return middleware.requirePermissions(true, permissions...)
}

// RequireAnyPermission 权限认证中间件 - 要求用户拥有任一权限(OR逻辑)
func RequireAnyPermission(permissions ...string) gin.HandlerFunc {
	middleware := NewAuthMiddleware()
	return middleware.requirePermissions(false, permissions...)
}

// RequireRoles 角色认证中间件 - 要求用户拥有指定角色(AND逻辑)
func RequireRoles(roles ...string) gin.HandlerFunc {
	middleware := NewAuthMiddleware()
	return middleware.requireRoles(true, roles...)
}

// RequireAnyRole 角色认证中间件 - 要求用户拥有任一角色(OR逻辑)
func RequireAnyRole(roles ...string) gin.HandlerFunc {
	middleware := NewAuthMiddleware()
	return middleware.requireRoles(false, roles...)
}

// RequireAdmin 管理员认证中间件 - 要求用户是管理员或超级管理员
func RequireAdmin() gin.HandlerFunc {
	middleware := NewAuthMiddleware()
	return middleware.requireAdmin()
}

// RequireSuperuser 超级管理员认证中间件 - 要求用户是超级管理员
func RequireSuperuser() gin.HandlerFunc {
	middleware := NewAuthMiddleware()
	return middleware.requireSuperuser()
}

// GlobalAuth 全局认证中间件 - 根据配置决定是否启用，并支持排除路由
// 支持三种匹配模式：
// 精确匹配：/api/auth/login
// 前缀匹配：/api/public/* (匹配所有以此开头的路由)
// 后缀匹配：*/public (匹配所有以此结尾的路由)
func GlobalAuth() gin.HandlerFunc {
	cfg := config.GetConfig()

	// 如果未启用全局认证，返回空中间件
	if !cfg.JWT.EnableGlobalAuth {
		return func(c *gin.Context) {
			c.Next()
		}
	}

	middleware := NewAuthMiddleware()
	excludeRoutes := cfg.JWT.ExcludeRoutes

	return func(c *gin.Context) {
		// 检查当前路由是否在排除列表中
		currentPath := c.Request.URL.Path
		for _, excludePath := range excludeRoutes {
			if isRouteMatched(currentPath, excludePath) {
				c.Next()
				return
			}
		}

		// 执行认证检查
		middleware.requireAuth()(c)
	}
}

// isRouteMatched 检查路由是否匹配（支持简单的通配符匹配）
func isRouteMatched(currentPath, excludePath string) bool {
	// 精确匹配
	if currentPath == excludePath {
		return true
	}

	// 支持前缀匹配（以*结尾）
	if strings.HasSuffix(excludePath, "*") {
		prefix := excludePath[:len(excludePath)-1]
		return strings.HasPrefix(currentPath, prefix)
	}

	// 支持后缀匹配（以*开头）
	if strings.HasPrefix(excludePath, "*") {
		suffix := excludePath[1:]
		return strings.HasSuffix(currentPath, suffix)
	}

	return false
}

// requireAuth 基础认证实现
func (m *AuthMiddleware) requireAuth() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 提取token
		token := m.extractToken(c)
		if token == "" {
			response.FailWithMessage(c, response.UNAUTHORIZED, "认证失败", "缺少访问令牌")
			c.Abort()
			return
		}

		// 验证token并获取用户信息
		userInfo, err := m.authService.VerifyToken(token)
		if err != nil {
			response.FailWithMessage(c, response.UNAUTHORIZED, "认证失败", err.Error())
			c.Abort()
			return
		}

		// 检查用户状态
		if userInfo.Status != 1 {
			response.FailWithMessage(c, response.FORBIDDEN, "账户被禁用", "您的账户已被禁用，请联系管理员")
			c.Abort()
			return
		}

		// 将用户信息存储到上下文中
		c.Set("user_id", userInfo.ID)
		c.Set("user", userInfo)
		c.Next()
	}
}

// requirePermissions 权限认证实现
func (m *AuthMiddleware) requirePermissions(requireAll bool, permissions ...string) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 先进行基础认证
		// m.requireAuth()(c)
		// if c.IsAborted() {
		// 	return
		// }

		// 获取用户信息
		userInfo, exists := c.Get("user")
		if !exists {
			response.FailWithMessage(c, response.UNAUTHORIZED, "认证失败", "用户信息获取失败")
			c.Abort()
			return
		}

		user := userInfo.(*serializers.AuthUserInfoResponse)

		// 超级管理员直接通过
		if user.IsSuperuser {
			c.Next()
			return
		}

		// 获取用户完整信息（包含角色权限）
		fullUser, err := m.getUserWithRole(user.ID)
		if err != nil {
			response.FailWithMessage(c, response.ERROR, "权限检查失败", "获取用户权限信息失败")
			c.Abort()
			return
		}

		// 检查权限
		if !m.checkPermissions(fullUser, requireAll, permissions...) {
			response.FailWithMessage(c, response.FORBIDDEN, "权限不足", "您没有执行此操作的权限")
			c.Abort()
			return
		}

		c.Next()
	}
}

// requireRoles 角色认证实现
func (m *AuthMiddleware) requireRoles(requireAll bool, roles ...string) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 从上下文获取已认证的用户信息（全局认证已处理）
		userInfo, exists := c.Get("user")
		if !exists {
			// 如果没有用户信息，执行基础认证
			m.requireAuth()(c)
			if c.IsAborted() {
				return
			}
			userInfo, exists = c.Get("user")
			if !exists {
				response.FailWithMessage(c, response.UNAUTHORIZED, "认证失败", "用户信息获取失败")
				c.Abort()
				return
			}
		}

		user := userInfo.(*serializers.AuthUserInfoResponse)

		// 超级管理员直接通过
		if user.IsSuperuser {
			c.Next()
			return
		}

		// 获取用户完整信息（包含角色）
		fullUser, err := m.getUserWithRole(user.ID)
		if err != nil {
			response.FailWithMessage(c, response.ERROR, "角色检查失败", "获取用户角色信息失败")
			c.Abort()
			return
		}

		// 检查角色
		if !m.checkRoles(fullUser, requireAll, roles...) {
			response.FailWithMessage(c, response.FORBIDDEN, "角色权限不足", "您的角色无权执行此操作")
			c.Abort()
			return
		}

		c.Next()
	}
}

// requireAdmin 管理员认证实现
func (m *AuthMiddleware) requireAdmin() gin.HandlerFunc {
	return m.requireRoles(false, models.RoleAdmin) // 使用OR逻辑，允许管理员角色
}

// requireSuperuser 超级管理员认证实现
func (m *AuthMiddleware) requireSuperuser() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 先进行基础认证
		// m.requireAuth()(c)
		// if c.IsAborted() {
		// 	return
		// }

		// 获取用户信息
		userInfo, exists := c.Get("user")
		if !exists {
			response.FailWithMessage(c, response.UNAUTHORIZED, "认证失败", "用户信息获取失败")
			c.Abort()
			return
		}

		user := userInfo.(*serializers.AuthUserInfoResponse)

		// 检查是否为超级管理员
		if !user.IsSuperuser {
			response.FailWithMessage(c, response.FORBIDDEN, "权限不足", "需要超级管理员权限")
			c.Abort()
			return
		}

		c.Next()
	}
}

// extractToken 从请求中提取token
func (m *AuthMiddleware) extractToken(c *gin.Context) string {
	// 优先从Authorization头获取
	authHeader := c.GetHeader("Authorization")
	if authHeader != "" && strings.HasPrefix(authHeader, "Bearer ") {
		return authHeader[7:] // 移除 "Bearer " 前缀
	}

	// 从查询参数获取
	if token := c.Query("token"); token != "" {
		return token
	}

	// 从表单参数获取
	if token := c.PostForm("token"); token != "" {
		return token
	}

	return ""
}

// getUserWithRole 获取用户完整信息（包含角色权限）
func (m *AuthMiddleware) getUserWithRole(userID uint64) (*models.User, error) {
	var user models.User
	err := m.db.Preload("Role").Where("id = ? AND status = 1", userID).First(&user).Error
	if err != nil {
		return nil, err
	}
	return &user, nil
}

// checkPermissions 检查用户权限
func (m *AuthMiddleware) checkPermissions(user *models.User, requireAll bool, permissions ...string) bool {
	if user.Role == nil {
		return false
	}

	userPermissions := user.Role.Permissions

	// 检查是否有全部权限
	for _, perm := range userPermissions {
		if perm == "*" || perm == "all" {
			return true
		}
	}

	if requireAll {
		// AND逻辑：需要拥有所有指定权限
		for _, requiredPerm := range permissions {
			found := false
			for _, userPerm := range userPermissions {
				if userPerm == requiredPerm {
					found = true
					break
				}
			}
			if !found {
				return false
			}
		}
		return true
	} else {
		// OR逻辑：只需要拥有任一权限
		for _, requiredPerm := range permissions {
			for _, userPerm := range userPermissions {
				if userPerm == requiredPerm {
					return true
				}
			}
		}
		return false
	}
}

// checkRoles 检查用户角色
func (m *AuthMiddleware) checkRoles(user *models.User, requireAll bool, roles ...string) bool {
	if user.Role == nil {
		return false
	}

	userRole := user.Role.Code

	if requireAll {
		// AND逻辑：需要拥有所有指定角色（通常不实用，因为一个用户只有一个角色）
		for _, requiredRole := range roles {
			if userRole != requiredRole {
				return false
			}
		}
		return true
	} else {
		// OR逻辑：只需要拥有任一角色
		for _, requiredRole := range roles {
			if userRole == requiredRole {
				return true
			}
		}
		return false
	}
}
